/*
 * @Author         : jiabao
 * @Description    :
 * @Date           : 2024-07-16 19:47:09
 * @FilePath       : /demo_cc/base/src/base_time.c
 */
#include "base_time.h"

static base_st_time_save gStTimeSave;

s32 base_delayMs(u32 msVal)
{
#ifdef _WIN32
    Sleep(msVal);
#elif __linux__
    sleep(msVal / 1000);
    usleep(msVal * 1000);
#endif
    return BASE_OK;
}

s32 base_delayS(u32 sVal)
{
#ifdef _WIN32
    Sleep(sVal * 1000);
#elif __linux__
    sleep(sVal);
#endif
    return BASE_OK;
}

s32 base_delayUs(u32 usVal)
{
#ifdef _WIN32
    LARGE_INTEGER freq, start, end;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&start);
    while (1)
    {
        QueryPerformanceCounter(&end);
        if ((end.QuadPart - start.QuadPart) * 1000000 / freq.QuadPart >= usVal)
        {
            break;
        }
    }
#elif __linux__
    usleep(usVal);
#endif
    return BASE_OK;
}

s32 base_time_save(u32 idx)
{
    if (idx >= BASE_TIME_SAVE_MAX)
    {
        printf("[base_time_save] save time max is:%d,please check parm\n", BASE_TIME_SAVE_MAX);
        return BASE_ERROR;
    }
#ifdef _WIN32
    static u08 flag = 0;
    if (flag == 0)
    {
        LARGE_INTEGER frequency;
        QueryPerformanceFrequency(&frequency);
        gStTimeSave.frequency = (double)frequency.QuadPart;
        flag = 1;
    }
    QueryPerformanceCounter(&gStTimeSave.timeSaveArr[idx]);
#elif __linux__
    gettimeofday(&gStTimeSave.timeSaveArr[idx], NULL);
#endif
    return BASE_OK;
}

static u08 *toStringEtimeUnit(base_e_time_unit timeUnit)
{
    if (timeUnit == BASE_TIME_UNIT_S)
    {
        return "s";
    }
    else if (timeUnit == BASE_TIME_UNIT_MS)
    {
        return "ms";
    }
    else if (timeUnit == BASE_TIME_UNIT_US)
    {
        return "us";
    }
    return "unknow";
}

ull base_time_use(u32 idx1, u32 idx2, base_e_time_unit timeUnit)
{
    if (idx1 >= BASE_TIME_SAVE_MAX || idx2 >= BASE_TIME_SAVE_MAX || timeUnit >= BASE_TIME_UNIT_MAX)
    {
        printf("[base_time_use] please check parm\n", BASE_TIME_SAVE_MAX);
        return BASE_ERROR;
    }
    ull useTime = 0;
#ifdef _WIN32
    if (timeUnit == BASE_TIME_UNIT_S)
    {
        useTime = (ull)((gStTimeSave.timeSaveArr[idx2].QuadPart - gStTimeSave.timeSaveArr[idx1].QuadPart) / gStTimeSave.frequency);
    }
    else if (timeUnit == BASE_TIME_UNIT_MS)
    {
        useTime = (ull)((gStTimeSave.timeSaveArr[idx2].QuadPart - gStTimeSave.timeSaveArr[idx1].QuadPart) / gStTimeSave.frequency * 1000);
    }
    else if (timeUnit == BASE_TIME_UNIT_US)
    {
        useTime = (ull)((gStTimeSave.timeSaveArr[idx2].QuadPart - gStTimeSave.timeSaveArr[idx1].QuadPart) / gStTimeSave.frequency * 1000 * 1000);
    }
#elif __linux__
    if (timeUnit == BASE_TIME_UNIT_S)
    {
        useTime = (ull)(gStTimeSave.timeSaveArr[idx2].tv_sec - gStTimeSave.timeSaveArr[idx1].tv_sec);
    }
    else if (timeUnit == BASE_TIME_UNIT_MS)
    {
        useTime = (ull)((gStTimeSave.timeSaveArr[idx2].tv_sec - gStTimeSave.timeSaveArr[idx1].tv_sec) * 1000);
        useTime += (ull)((gStTimeSave.timeSaveArr[idx2].tv_usec - gStTimeSave.timeSaveArr[idx1].tv_usec) / 1000);
    }
    else if (timeUnit == BASE_TIME_UNIT_US)
    {
        useTime = (ull)((gStTimeSave.timeSaveArr[idx2].tv_sec - gStTimeSave.timeSaveArr[idx1].tv_sec) * 1000 * 1000);
        useTime += (ull)((gStTimeSave.timeSaveArr[idx2].tv_usec - gStTimeSave.timeSaveArr[idx1].tv_usec));
    }
#endif
    printf("%d → %d use time:%llu %s\n", idx1, idx2, useTime, toStringEtimeUnit(timeUnit));
    return useTime;
}

s32 base_time_test()
{
    base_time_save(0);
    base_delayS(5);
    base_time_save(1);
    base_time_use(0, 1, BASE_TIME_UNIT_S);

    base_time_save(0);
    base_delayMs(50);
    base_time_save(1);
    base_time_use(0, 1, BASE_TIME_UNIT_MS);

    base_time_save(0);
    base_delayUs(50);
    base_time_save(1);
    base_time_use(0, 1, BASE_TIME_UNIT_US);

    return BASE_OK;
}

s32 base_time_test11()
{
    // clock_t start, end;

    // // clock为该程序从启动到函数调用占用CPU的时间
    // start = clock();
    // base_delayS(5);
    // end = clock();
    // printf("delay 5 s,use clock test:%lf s\n", (double)(end - start) / CLOCKS_PER_SEC);

    // start = clock();
    // base_delayMs(500);
    // end = clock();
    // printf("delay 500 ms,use clock test:%lf \n", (double)(end - start) / CLOCKS_PER_SEC * 1000);

    // start = clock();
    // base_delayUs(500);
    // end = clock();
    // printf("delay 500 us,use clock test:%lf\n", (double)(end - start) / CLOCKS_PER_SEC * 1000 * 1000);
    /*
        delay 5 s,use clock test:5.008000 s
        delay 500 ms,use clock test:509.000000
        delay 500 us,use clock test:0.000000
    */

    // LARGE_INTEGER timeStart; // 开始时间
    // LARGE_INTEGER timeEnd;   // 结束时间

    // LARGE_INTEGER frequency; // 计时器频率
    // QueryPerformanceFrequency(&frequency);
    // double quadpart = (double)frequency.QuadPart; // 计时器频率

    // QueryPerformanceCounter(&timeStart);
    // base_delayS(5);
    // QueryPerformanceCounter(&timeEnd);

    // // 得到两个时间的耗时
    // double elapsed = (timeEnd.QuadPart - timeStart.QuadPart) / quadpart;
    // printf("use:%lf\n", elapsed);

    // QueryPerformanceCounter(&timeStart);
    // base_delayMs(50);
    // QueryPerformanceCounter(&timeEnd);

    // // 得到两个时间的耗时
    // elapsed = (timeEnd.QuadPart - timeStart.QuadPart) / quadpart;
    // printf("use:%lf\n", elapsed);

    // QueryPerformanceCounter(&timeStart);
    // base_delayUs(50);
    // QueryPerformanceCounter(&timeEnd);

    // // 得到两个时间的耗时
    // elapsed = (timeEnd.QuadPart - timeStart.QuadPart) / quadpart;
    // printf("use:%lf\n", elapsed);
    /*
        use:5.001654
        use:0.058203
        use:0.000051
    */

    return BASE_OK;
}